home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dviapollo / xinteract.c < prev   
C/C++ Source or Header  |  1990-10-01  |  14KB  |  529 lines

  1. /* @(#)xinteract.c    1.6 2/18/87 */
  2. #include "header.h"
  3. #include <X/Xlib.h>
  4. #include "gray1.bitmap"
  5. #define DEFAULTFONT "vtsingle"
  6. #define BUTTONMARGIN 4
  7. Window frame;
  8. Window panel;
  9. Window textwindow;
  10. int screenheight = 0;
  11. int screenwidth = 0;
  12. int textwindowheight = 0;
  13. /* State information for the filename item. */
  14. Window filename_button;
  15. char *current_file_name;
  16. int current_file_name_index;
  17. int current_file_name_length;
  18. /* State information for the region that displays the error messages. */
  19. Window error_button;
  20. char *error_message;
  21. /* State information for the page number slider. */
  22. /* This window has all of the graphics for the slider. */
  23. Window page_window;
  24. /* This window just has the slider bar itself.  It's a subwindow of */
  25.  /* page_window. */
  26. Window page_subwindow;
  27. Pixmap page_tile;
  28. int page_max = 1;
  29. int page_current = 1;
  30. int page_displayed;
  31. /* X coordinate of page_subwindow in page_window. */
  32. int pager_x = 0;
  33. #define PAGER_WIDTH 100
  34. /* Whether or not to carry on in reverse video. */
  35. BOOLEAN reversevideo;
  36. Pixmap foreground, background;
  37. XAssocTable *callouttable; /* Assoc table for storing mapping from */
  38. /* buttons to callout routines. */
  39. XAssocTable *offsets; /* Assoc table to remember how much the labels */
  40.               /* need to be shifted right to be centered. */
  41. Font font;
  42. FontInfo fontinfo;
  43.  
  44. BOOLEAN reverse_video_p ();
  45. char *realloc ();
  46.  
  47. /* On window w, coordinates (x,y) draw the text in chars. */
  48. void dotext (w, x, y, chars)
  49.      Window w;
  50.      int x, y;
  51.      char *chars;
  52. {
  53.   XTextPad (w, x, y, chars, strlen (chars), font, 0, 0,
  54.         WhitePixel, BlackPixel, reversevideo?GXor:GXandInverted,
  55.         AllPlanes);
  56. }
  57.  
  58. void black_box (x, y, width, height)
  59.      int x, y, width, height;
  60. {
  61.   XPixFill (textwindow, x, y, width, height,
  62.         reversevideo?WhitePixel:BlackPixel, 0,
  63.         GXcopy, AllPlanes);
  64. }
  65.  
  66. int screen_height ()
  67. {
  68.   return (textwindowheight);
  69. }
  70.  
  71. /* Cribbed from /usr/misc/X/libsun/initial.c. */
  72. static unsigned char InvPix[256];
  73.  
  74. SetUpInvPix()
  75. {
  76.     register int i;
  77.  
  78.     for (i = 255; i >= 0; i--) {
  79.     register int j = 1, k = 128, l = 8;
  80.  
  81.     while (l--) {
  82.         if ((i & j) != 0)
  83.         InvPix[i] |= k;
  84.         j <<= 1;
  85.         k >>= 1;
  86.     }
  87.     }
  88. }
  89.  
  90. /* Cribbed from /usr/misc/X/libsun/util.c. */
  91. InvertPixelOrder(p, n)
  92.     register unsigned short *p;
  93.     register int n;
  94. {
  95.     for (; n--; p++) {
  96.         register unsigned short l = (*p & 0xff), h = (*p >> 8)&0xff;
  97.         unsigned short         old = *p;
  98.  
  99.         *p = (unsigned short) ((InvPix[l] << 8) | InvPix[h]);
  100.     }
  101. }
  102.  
  103. /* Read a character from a font file, with the given width and height. */
  104.  /* For X, a CharImage is a Pixmap. */
  105. CharImage read_char (pxlfp, width, height)
  106.      FILE *pxlfp;
  107.      int width, height;
  108. {
  109.   static short *bitmapbuf = NULL;
  110.   static int bitmapbufsize = 0;
  111.   register int nshorts, i, col, nints;
  112.   register short *dp, *sp;
  113.   static int buffer[8];
  114.   Bitmap result;
  115.  
  116.   if (!bitmapbuf) {
  117.     bitmapbuf = (short *) malloc (1);
  118.     bitmapbufsize = 1;
  119.   };
  120.   if (bitmapbufsize < BitmapSize (width, height)) {    
  121.     bitmapbufsize = BitmapSize (width, height);
  122.     bitmapbuf = (short *)realloc (bitmapbuf, bitmapbufsize);
  123.   };
  124.   if (!bitmapbuf) {
  125.     fprintf (stderr, "Memory allocation failed in read_char.\n");
  126.     exit (1);
  127.   }
  128.   nshorts = (width + 15) >> 4;
  129.   nints = (nshorts + 1) >> 1;
  130.   dp = bitmapbuf;
  131.   for (col = 0; col < height; col++) {
  132.     fread(buffer, 4, nints, pxlfp);
  133.     sp = (short *) &buffer[0];
  134.     for (i = nshorts; i > 0; i--) *dp++ = *sp++;
  135.   }
  136.   InvertPixelOrder (bitmapbuf, BitmapSize (width, height) >> 1);
  137.   result = XStorePixmapXY (width, height, bitmapbuf);
  138.   if (!result) {
  139.     fprintf (stderr, "Pixmap creation failed in read_char.\n");
  140.     exit (1);
  141.   }
  142.   return ((CharImage) result);
  143. }
  144.  
  145. void show_char (x, y, width, height, image)
  146.      int x, y, width, height;
  147.      CharImage image;
  148. {
  149.   if (((x + width) >= 0) &&
  150.       (x < screenwidth) &&
  151.       ((y + height) >= 0) &&
  152.       (y < screenheight)) {
  153.       XPixmapPut (textwindow, 0, 0, x, y, width, height, (Pixmap) image,
  154.           reversevideo?GXor:GXandInverted, AllPlanes);
  155.     }
  156. };
  157.  
  158. void clearscreen ()
  159. {
  160.   XClear (textwindow);
  161. }
  162.  
  163. void lock_canvas ()
  164. {
  165. }
  166.  
  167. void unlock_canvas ()
  168. {
  169. }
  170.  
  171. char *curfilename ()
  172. {
  173.   return (current_file_name);
  174. }
  175.  
  176. /* Refresh the image of the slider. */
  177. void refresh_slider ()
  178. {
  179.   char buffer [20];
  180.   XClear (page_window);
  181.   XClear (page_subwindow);
  182.   if (page_max > 1) {
  183.     sprintf (buffer, "Pages: [%d]", page_displayed);
  184.     dotext (page_window, BUTTONMARGIN, BUTTONMARGIN, buffer);
  185.     XTileSet (page_subwindow, 0, 0,
  186.           (int) ((float) (page_displayed - 1) / (page_max - 1) * PAGER_WIDTH),
  187.           fontinfo.height, page_tile);
  188.   }
  189. }
  190.  
  191. /* Set the slider so that it has pages pages displayed. */
  192. void show_slider (pages)
  193.      int pages;
  194. {
  195.   char buffer [20];
  196.  
  197.   page_max = pages;
  198.   page_current = 1;
  199.   page_displayed = 1;
  200.   if (page_max == 1) {
  201.     XUnmapWindow (page_subwindow);
  202.   } else {
  203.     XMapWindow (page_subwindow);
  204.     sprintf (buffer, "%d", page_max);
  205.     XConfigureWindow (page_subwindow,
  206.               BUTTONMARGIN +
  207.               (strlen ("Page: [] ") + strlen (buffer) + 1) *
  208.               fontinfo.width,
  209.               BUTTONMARGIN,
  210.               PAGER_WIDTH,
  211.               fontinfo.height);
  212.   }
  213.   refresh_slider ();
  214. }
  215.  
  216. /* Update the current (not the maximum) number of pages displayed on */
  217. /* the slider.*/
  218. void update_slider (pages)
  219.      int pages;
  220. {
  221.   page_current = pages;
  222.   page_displayed = pages;
  223.   refresh_slider ();
  224. }
  225.  
  226. void curpage_from_x (event)
  227.      XEvent *event;
  228. {
  229.   int new_displayed;
  230.   if (page_max > 1) {
  231.     new_displayed = (int) ((float) ((XKeyEvent *) event) -> x /
  232.                PAGER_WIDTH * (page_max - 1) + 0.5) + 1;
  233.     if (new_displayed != page_displayed) {
  234.       page_displayed = new_displayed;
  235.       refresh_slider ();
  236.     };
  237.   }
  238. }
  239.  
  240. int lines_to_y (lines)
  241.      int lines;
  242. {
  243.   return (lines * (fontinfo.height + 3 * BUTTONMARGIN) +
  244.       BUTTONMARGIN);
  245. }
  246.  
  247. int chars_to_x (chars)
  248.      int chars;
  249. {
  250.   return (chars * fontinfo.width - BUTTONMARGIN);
  251. }
  252.  
  253. /* This puts a button image on the screen.  It is called by 
  254.    create_buttons.
  255.    name is the label for the button.  It needs to be centered.
  256.    width is the width in characters of the button.
  257.    x,y, are the position of the button on a character grid.
  258.    callout is the procedure to call when the button is pushed.
  259.    */
  260. void create_a_button (name, width, x, y, callout)
  261.      char *name;
  262.      int width, x, y;
  263.      void (*callout) ();
  264. {
  265.   Window created;
  266.   created = XCreateWindow (panel, chars_to_x (x), lines_to_y (y),
  267.                width * fontinfo.width + 2 * BUTTONMARGIN,
  268.                fontinfo.height + 2 * BUTTONMARGIN, 1,
  269.                foreground, background);
  270.   XStoreName (created, name);
  271.   XMakeAssoc (callouttable, created, callout);
  272.   XMakeAssoc (offsets, created,
  273.           ((width - strlen (name)) >> 1) * fontinfo.width);
  274.   XSelectInput (created, ButtonReleased | ExposeWindow);
  275. }
  276.  
  277. void update_filename ()
  278. {
  279.   char *namestart;
  280.  
  281.   if (strlen (current_file_name) > 19) {
  282.     namestart = current_file_name + (strlen (current_file_name) - 19);
  283.   } else {
  284.     namestart = current_file_name;
  285.   }
  286.   XClear (filename_button);
  287.   {
  288.     char buffer [35];
  289.  
  290.     sprintf (buffer, "Filename: %s", namestart);
  291.     dotext (filename_button, BUTTONMARGIN, BUTTONMARGIN, buffer);
  292.   }
  293. }
  294.  
  295. void update_error ()
  296. {
  297.   XClear (error_button);
  298.   dotext (error_button, BUTTONMARGIN, BUTTONMARGIN, error_message);
  299. }
  300.  
  301. void showerror (string)
  302.      char *string;
  303. {
  304.   error_message = string;
  305.   update_error ();
  306. }
  307.  
  308. void clearerror ()
  309. {
  310.   error_message = "";
  311.   update_error ();
  312. }
  313.  
  314. void main (argc, argv)
  315.      int argc;
  316.      char **argv;
  317. {
  318.   int downx = 0, downy = 0;
  319.   int panelheight;
  320.  
  321.   SetUpInvPix ();
  322.   if ((PXLpath = getenv ("BGPXLPATH")) == NULL)
  323.     PXLpath = FONTAREA;
  324.   error_message = "";
  325.   current_file_name = malloc (10);
  326.   current_file_name_index = 0;
  327.   current_file_name_length = 10;
  328.   { 
  329.     char *thisch = argv [1];
  330.     if (thisch) {
  331.       for (;*thisch;thisch++) {
  332.     vector_push_extend (¤t_file_name_index,
  333.                 ¤t_file_name_length,
  334.                 ¤t_file_name,
  335.                 sizeof (char));
  336.     current_file_name [current_file_name_index - 1] = *thisch;
  337.       }
  338.     }
  339.   }
  340.   vector_push_extend (¤t_file_name_index,
  341.               ¤t_file_name_length,
  342.               ¤t_file_name,
  343.               sizeof (char));
  344.   current_file_name [current_file_name_index - 1] = '\0';
  345.   if (!XOpenDisplay ("unix:0")) {
  346.     fprintf (stderr, "Could not open the display.\n");
  347.     exit (1);
  348.   };
  349.   reversevideo = reverse_video_p (argv [0]);
  350.   foreground = reversevideo?WhitePixmap:BlackPixmap;
  351.   background = reversevideo?BlackPixmap:WhitePixmap;
  352.   page_tile = XStorePixmapXY (gray1_width, gray1_height, gray1_bits);
  353.   {
  354.     char *fontname = XGetDefault (argv [0], "Font");
  355.     if (fontname == NULL) fontname = DEFAULTFONT;
  356.     if (!(font = XGetFont (fontname))) {
  357.       fprintf (stderr, "Couldn't open font %s for buttons.\n", fontname);
  358.       exit (1);
  359.     };
  360.     XQueryFont (font, &fontinfo);
  361.   }
  362.   /* This is the inside height. */
  363.   panelheight = lines_to_y (2);
  364.   {
  365.     OpaqueFrame oframe;
  366.     WindowInfo info;
  367.     char defgeom [20];
  368.     
  369.     oframe.border =     foreground;
  370.     oframe.background = background;
  371.     oframe.bdrwidth = 1;
  372.     sprintf (defgeom, "=%dx%d+0+0",
  373.          DisplayWidth()-2,
  374.          DisplayHeight()-2);
  375.     frame = XCreate (argv [0], argv [0],
  376.               0, defgeom,
  377.               &oframe,
  378.              chars_to_x (70) + BUTTONMARGIN +PAGER_WIDTH,
  379.              2 * panelheight);
  380.     XSelectInput (frame, ExposeWindow | ButtonPressed
  381.           | ButtonReleased
  382.           | KeyPressed);
  383.     XQueryWindow (frame, &info);
  384.     screenwidth = info.width;
  385.     screenheight = info.height;
  386.     panel = XCreateWindow (frame, -1, -1, screenwidth,
  387.                panelheight, 1, foreground, background);
  388.     textwindowheight = screenheight - panelheight;
  389.     /* The border pixmap below is background so we can have an */
  390.     /* invisible border.  We want a border, though, so that this */
  391.     /* window lines up with the buttons. */
  392.     filename_button = XCreateWindow (panel,
  393.                      chars_to_x (0), lines_to_y (0),
  394.                      chars_to_x (30), lines_to_y (1),
  395.                      1, background, background);
  396.     XSelectInput (filename_button, ExposeWindow);
  397.     error_button = XCreateWindow (panel,
  398.                   chars_to_x (0), lines_to_y (1),
  399.                   chars_to_x (30), lines_to_y (1),
  400.                   1, background, background);
  401.     XSelectInput (error_button, ExposeWindow);
  402.     page_window = XCreateWindow (panel,
  403.                  chars_to_x (57), lines_to_y (0),
  404.                  chars_to_x (30) + PAGER_WIDTH,
  405.                  lines_to_y (1),
  406.                  1, background, background);
  407.     XSelectInput (page_window, ExposeWindow);
  408.     /* The real shape of the page_subwindow will be determined when */
  409.     /* show_slider is called. */
  410.     page_subwindow = XCreateWindow (page_window, 1, 1, 1, 1,
  411.                     1,
  412.                     foreground, background);
  413.     XSelectInput (page_subwindow, LeaveWindow | MouseMoved |
  414.           ButtonPressed | ButtonReleased);
  415.     callouttable = XCreateAssocTable (2);
  416.     offsets = XCreateAssocTable (2);
  417.     create_buttons ();
  418.     XMapSubwindows (panel);
  419.     /* + 1 and -1 below are to account for the border around the pane. */ 
  420.     textwindow =
  421.       XCreateWindow (frame, 0, panelheight + 1,
  422.              screenwidth, textwindowheight,
  423.              0, foreground, background);
  424.     XSelectInput (textwindow, ExposeWindow);
  425.   }
  426.   XMapSubwindows (frame);
  427.   XMapWindow (frame);
  428.   reset_scroll ();
  429.   if (current_file_name [0]) {
  430.     load_proc ();
  431.   };
  432.   for (;;) {
  433.     char *string;
  434.     XEvent e;
  435.     void (*callout) ();
  436.  
  437.     XNextEvent (&e);
  438.     callout = (void (*)()) XLookUpAssoc (callouttable, e.window);
  439.     switch (e.type) {
  440.     case KeyPressed:
  441.       {
  442.     int length;
  443.     char *string;
  444.     string = XLookupMapping (&e, &length);
  445.     if (length) {
  446.       for (;length; string++,length--) {
  447.         if (*string == '\010' || *string == '\177') {
  448.           if (*current_file_name) {
  449.         current_file_name_index--;
  450.         current_file_name [current_file_name_index - 1] = '\0';
  451.           }
  452.         } else {
  453.           current_file_name [current_file_name_index - 1] = *string;
  454.           vector_push_extend (¤t_file_name_index,
  455.                   ¤t_file_name_length,
  456.                   ¤t_file_name,
  457.                   sizeof (char));
  458.           current_file_name [current_file_name_index - 1] = '\0';
  459.         }
  460.       }
  461.     }
  462.     update_filename ();
  463.       }
  464.       break;
  465.     case MouseMoved:
  466.       /* The event must be in page_subwindow. */
  467.       curpage_from_x (&e);
  468.       break;
  469.     case LeaveWindow:
  470.       /* The event must be in page_subwindow. */
  471.       page_displayed = page_current;
  472.       refresh_slider ();
  473.       break;
  474.     case ButtonPressed:
  475.       if (e.window == page_subwindow) {
  476.     curpage_from_x (&e);
  477.     page_current = page_displayed;
  478.     goto_page (page_current);
  479.       } else if (!callout) {
  480.     buttondown (((XKeyEvent *) &e) -> x,
  481.             ((XKeyEvent *) &e) -> y);
  482.       };
  483.       break;
  484.     case ButtonReleased:
  485.       if (e.window == page_subwindow) {
  486.     /* Do nothing. */
  487.       } else if (callout) {
  488.     (*callout) ();
  489.       } else {
  490.     buttonup (((XKeyEvent *) &e) -> x,
  491.           ((XKeyEvent *) &e) -> y);
  492.       };
  493.       break;
  494.     case ExposeWindow:
  495.       if (e.window == filename_button) {
  496.     update_filename ();
  497.       } else if (e.window == error_button) {
  498.     update_error ();
  499.       } else if (e.window == page_window ) {
  500.     refresh_slider ();
  501.       } else if (callout) {
  502.     char *name;
  503.     int offset;
  504.  
  505.     offset = (int) XLookUpAssoc (offsets, e.window);
  506.     XFetchName (e.window, &name);
  507.     dotext (e.window,
  508.         BUTTONMARGIN + offset, BUTTONMARGIN,
  509.         name);
  510.     free (name);
  511.       } else if ((e.window == frame) &&
  512.          (((XExposeEvent *) &e) -> subwindow == 0)) {
  513.     if ((screenwidth != ((XExposeEvent *) &e) -> width) ||
  514.         (screenheight != ((XExposeEvent *) &e) -> height)) {
  515.           screenwidth = ((XExposeEvent *) &e) -> width;
  516.           screenheight = ((XExposeEvent *) &e) -> height;
  517.           textwindowheight = screenheight - panelheight;
  518.           XChangeWindow (panel, screenwidth, panelheight);
  519.           XChangeWindow (textwindow, screenwidth,
  520.                  textwindowheight);
  521.         }
  522.       } else if (e.window == textwindow) {
  523.     refresh_proc ();
  524.       };
  525.       break;
  526.     };
  527.   };
  528. };
  529.